/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.core.editpart;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.Animation;
import org.eclipse.draw2d.ConnectionAnchor;
import org.eclipse.draw2d.ConnectionLayer;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.FreeformLayer;
import org.eclipse.draw2d.FreeformLayout;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.ManhattanConnectionRouter;
import org.eclipse.draw2d.MarginBorder;
import org.eclipse.draw2d.ShortestPathConnectionRouter;
import org.eclipse.draw2d.XYLayout;
import org.eclipse.gef.AccessibleEditPart;
import org.eclipse.gef.CompoundSnapToHelper;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.DragTracker;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.LayerConstants;
import org.eclipse.gef.Request;
import org.eclipse.gef.SnapToGeometry;
import org.eclipse.gef.SnapToGrid;
import org.eclipse.gef.SnapToGuides;
import org.eclipse.gef.SnapToHelper;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.RootComponentEditPolicy;
import org.eclipse.gef.editpolicies.SnapFeedbackPolicy;
import org.eclipse.gef.requests.SelectionRequest;
import org.eclipse.gef.rulers.RulerProvider;
import org.eclipse.gef.tools.DeselectAllTracker;
import org.eclipse.gef.tools.MarqueeDragTracker;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.AccessibleEvent;

import com.cea.papyrus.core.IPapyrusUIConstants;
import com.cea.papyrus.core.actions.CloseDiagramAction;
import com.cea.papyrus.core.commands.diagram.CloseDiagramCommand;
import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;

/**
 * 
 */
public class DiagramEditPart extends ContainerEditPart
//extends ContainerWithSemanticEditPart
implements LayerConstants, IUMLDiagramElementEditPart {
	/** debug channel */
	protected final static int channel = 27;
	
	/**
	 * 
	 * 
	 * @return 
	 */
	@Override
	protected AccessibleEditPart createAccessible() {
		return new AccessibleGraphicalEditPart(){
			@Override
			public void getName(AccessibleEvent e) {
				e.result = "Diagram";
			}
		};
	}
	
/**
 * The element that is associated is Diagram.
 * 
 * @param modelManager 
 * @param diagram 
 */
	public  DiagramEditPart(Diagram diagram,ModelManager modelManager) {
		super(diagram,modelManager);
	}
	
	/**
	 * we need to know what is the associated element.
	 * 
	 * @return the diagram element
	 */
	
	public Diagram getDiagram(){
		return (Diagram) getModel();
	}
	
	
	/**
	 * Installs EditPolicies specific to this.
	 */
	@Override
	protected void createEditPolicies(){
		super.createEditPolicies();
		
		installEditPolicy(EditPolicy.NODE_ROLE, null);
		installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE, null);
		installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE, null);
		installEditPolicy(EditPolicy.COMPONENT_ROLE, new RootComponentEditPolicy());
		installEditPolicy(EditPolicy.LAYOUT_ROLE, new LayoutEditPolicy(
				(XYLayout)getContentPane().getLayoutManager()));
		installEditPolicy("Snap Feedback", new SnapFeedbackPolicy()); //$NON-NLS-1$
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.gef.editparts.AbstractEditPart#performRequest(org.eclipse.gef.Request)
	 */
	/**
	 * 
	 * 
	 * @param request 
	 */
	@Override
	public void performRequest(Request request) {
		
		
		super.performRequest(request);
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.gef.editparts.AbstractEditPart#getCommand(org.eclipse.gef.Request)
	 */
	@Override
	public Command getCommand(Request request) {
		if(CloseDiagramAction.CLOSE_DIAGRAM_ACTION_REQUEST.equals(request.getType())) {
			// return the command to close if diagram is actually visible
			if(getDiagram().isIsVisible()) {
				return new CloseDiagramCommand(getDiagram());
			}
		}
		return super.getCommand(request);
	}
	
	/**
	 * Returns a Figure to represent this.
	 * 
	 * @return  Figure.
	 */
	@Override
	protected IFigure createFigure() {
		Figure f = new FreeformLayer();
//		f.setBorder(new GroupBoxBorder("Diagram"));
		f.setLayoutManager(new FreeformLayout());
		f.setBorder(new MarginBorder(5));
//		 Create the static router for the connection layer
		ConnectionLayer connLayer = (ConnectionLayer)getLayer(LayerConstants.CONNECTION_LAYER);
		
		if(IPapyrusUIConstants.COMPOSITE_STRUCTURE_DIAGRAM!=getDiagram().getType()){
			connLayer.setConnectionRouter(new ShortestPathConnectionRouter(f));}
		else{
			connLayer.setConnectionRouter(new ManhattanConnectionRouter());}
		
		return f;
	}
	
	 /**
 	 * 
 	 * 
 	 * @param index 
 	 * @param child 
 	 */
 	public void addExplicitEditpart(EditPart child, int index){
		 this.addChild(child, index);
	 }
	
	/**
	 * 
	 * 
	 * @param adapter 
	 * 
	 * @return 
	 * 
	 * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
	 */
	@Override
	public Object getAdapter(Class adapter) {
		if (adapter == SnapToHelper.class) {
			List snapStrategies = new ArrayList();
			Boolean val = (Boolean)getViewer().getProperty(RulerProvider.PROPERTY_RULER_VISIBILITY);
			if ((val != null) && val.booleanValue()) {
				snapStrategies.add(new SnapToGuides(this));
			}
			val = (Boolean)getViewer().getProperty(SnapToGeometry.PROPERTY_SNAP_ENABLED);
			if ((val != null) && val.booleanValue()) {
				snapStrategies.add(new SnapToGeometry(this));
			}
			val = (Boolean)getViewer().getProperty(SnapToGrid.PROPERTY_GRID_ENABLED);
			if ((val != null) && val.booleanValue()) {
				snapStrategies.add(new SnapToGrid(this));
			}
			
			if (snapStrategies.size() == 0) {
				return null;
			}
			if (snapStrategies.size() == 1) {
				return snapStrategies.get(0);
			}
			
			SnapToHelper ss[] = new SnapToHelper[snapStrategies.size()];
			for (int i = 0; i < snapStrategies.size(); i++) {
				ss[i] = (SnapToHelper)snapStrategies.get(i);
			}
			return new CompoundSnapToHelper(ss);
		}
		return super.getAdapter(adapter);
	}
	
	/**
	 * 
	 * 
	 * @param req 
	 * 
	 * @return 
	 */
	@Override
	public DragTracker getDragTracker(Request req){
		if ((req instanceof SelectionRequest) 
				&& (((SelectionRequest)req).getLastButtonPressed() == 3)) {
			return new DeselectAllTracker(this);
		}
		return new MarqueeDragTracker();
	}
	
	/**
	 * Returns <code>NULL</code> as it does not hold any connections.
	 * 
	 * @param editPart 
	 * 
	 * @return  ConnectionAnchor
	 */
	@Override
	public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart editPart) {
		return null;
	}
	
	/**
	 * Returns <code>NULL</code> as it does not hold any connections.
	 * 
	 * @param y 
	 * @param x 
	 * 
	 * @return  ConnectionAnchor
	 */
	public ConnectionAnchor getSourceConnectionAnchor(int x, int y) {
		return null;
	}
	
	/**
	 * Returns <code>NULL</code> as it does not hold any connections.
	 * 
	 * @param editPart 
	 * 
	 * @return  ConnectionAnchor
	 */
	@Override
	public ConnectionAnchor getTargetConnectionAnchor(ConnectionEditPart editPart) {
		return null;
	}
	
	/**
	 * Returns <code>NULL</code> as it does not hold any connections.
	 * 
	 * @param y 
	 * @param x 
	 * 
	 * @return  ConnectionAnchor
	 */
	public ConnectionAnchor getTargetConnectionAnchor(int x, int y) {
		return null;
	}
	
	/**
	 * 
	 */
	@Override
	protected void refreshVisuals() {

		Animation.markBegin();
		
		
		
		ConnectionLayer cLayer = (ConnectionLayer) getLayer(CONNECTION_LAYER);
		cLayer.setAntialias(SWT.ON);

		//cLayer.setConnectionRouter(new ShortestPathConnectionRouter(getFigure()));
		
		
		Animation.run(400);
	}

	
}
